package model;

import java.util.Iterator;
import java.util.LinkedList;


public class Trayectoria {

	private static final int PASO = 1;
	LinkedList<Posicion> trayecto;
	
	
	public Trayectoria() {
		this.trayecto = new LinkedList<Posicion>();
		
	}
	
	public Trayectoria (Posicion unaPosicion) {
		this.trayecto = new LinkedList<Posicion>();
		this.agregarUnaPosicion(unaPosicion);
	}
	

	public Posicion getSiguietePosicion(Posicion miPosicion, Posicion posicionAnterior) {
		
		Posicion resultado;
		
		if (this.tieneSiguientePosicion()) {
			resultado = this.trayecto.getFirst();
			this.trayecto.removeFirst();
		} else {
			resultado = this.calcularSiguientePosicion(miPosicion,posicionAnterior);
		}
		
		return resultado;
	}
	
	
	public boolean tieneSiguientePosicion() {
		
		return !(this.trayecto.isEmpty());
	}
	
	/*Agrega una posicion a la trayectoria, esta nueva posicion sería la ultima posicion del trayecto*/
	private void agregarUnaPosicion(Posicion unaPosicion) {
		this.trayecto.addLast(unaPosicion);
	}
	
	/*Cuando un avion no tiene siguiente posicion, le crea una trayectoria automaticamente para que no se frene*/
	public Posicion calcularSiguientePosicion(Posicion miPosicion, Posicion posicionAnterior){
		
			Posicion resultado = new Posicion();
			
			//Si la posicion anterior es nula, significa que el avion recien se crea
			if (posicionAnterior == null) {
				if(miPosicion.getX()==Posicion.getPosicionMinima()) {
					resultado.setX(miPosicion.getX()+getPaso());
					resultado.setY(miPosicion.getY());
				}
				if(miPosicion.getX()==Posicion.getPosicionMaxima()) {
					resultado.setX(miPosicion.getX()-getPaso());
					resultado.setY(miPosicion.getY());
				}
				if(miPosicion.getY()==Posicion.getPosicionMinima()) {
					resultado.setX(miPosicion.getX());
					resultado.setY(miPosicion.getY()+getPaso());
				}
				if(miPosicion.getY()==Posicion.getPosicionMaxima()) {
					resultado.setX(miPosicion.getX());
					resultado.setY(miPosicion.getY()-getPaso());
				}
			
			} else {
				if (miPosicion.tienePosicionAbajo(posicionAnterior)) {
					resultado.setX(miPosicion.getX());
					resultado.setY(miPosicion.getY()-getPaso());
				}
				if (miPosicion.tienePosicionAdelante(posicionAnterior)) {
					resultado.setX(miPosicion.getX()-getPaso());
					resultado.setY(miPosicion.getY());
				}
				if (miPosicion.tienePosicionArriba(posicionAnterior)) {
					resultado.setX(miPosicion.getX());
					resultado.setY(miPosicion.getY()+getPaso());
				}
				if  (miPosicion.tienePosicionAtras(posicionAnterior)) {
					resultado.setX((miPosicion.getX()+getPaso()));
					resultado.setY(miPosicion.getY());
				}
				if  (miPosicion.tienePosicionAbajoAdelante(posicionAnterior)) {
					resultado.setX((miPosicion.getX()-getPaso()));
					resultado.setY(miPosicion.getY()-getPaso());
				}
				if  (miPosicion.tienePosicionAbajoAtras(posicionAnterior)) {
					resultado.setX((miPosicion.getX()+getPaso()));
					resultado.setY(miPosicion.getY()-getPaso());
				}
				if  (miPosicion.tienePosicionArribaAtras(posicionAnterior)) {
					resultado.setX((miPosicion.getX()+getPaso()));
					resultado.setY(miPosicion.getY()+getPaso());
				}
				if  (miPosicion.tienePosicionArribaAdelante(posicionAnterior)) {
					resultado.setX((miPosicion.getX()-getPaso()));
					resultado.setY(miPosicion.getY()+getPaso());
				}
			}
			
			return resultado;
		
	}

	/*Agrega una posicion a la trayectoria, esta nueva posicion sería la primera posicion del nuevo trayecto.
	 *El resto de posiciones del trayecto anterior se borraran */
	public void cambiarRumbo (Posicion unaPosicion) {
		this.trayecto.clear();
		this.trayecto.add(unaPosicion);
	}
	
	/*Agrega al trayecto, todas las posiciones intermedias por las que se debe pasar para llegar de
	 * una posicion a otra.
	 *IMPORTANTE:   */
	public void agregarTramo (Posicion inicio, Posicion fin) {
		
		int deltaX = (fin.getX() - inicio.getX());
		int deltaY = (fin.getY() - inicio.getY());
		int indiceX = 0;
		int indiceY = 0;
		boolean coincideCoordenadaX = (fin.getX() == inicio.getX()+indiceX);
		boolean coincideCoordenadaY = (fin.getY() == inicio.getY()+indiceY);
		
		//this.agregarUnaPosicion(inicio);
		
		while (!coincideCoordenadaX && !coincideCoordenadaY) {
			
			if (deltaX > 0) {
				if (deltaY > 0) {
					Posicion nuevaPosicion = new Posicion(inicio.getX()+indiceX,inicio.getY()+indiceY);
					this.agregarUnaPosicion(nuevaPosicion);
					coincideCoordenadaY = (fin.getY() == inicio.getY()+indiceY);
				} else {
					Posicion nuevaPosicion = new Posicion(inicio.getX()+indiceX,inicio.getY()-indiceY);
					this.agregarUnaPosicion(nuevaPosicion);
					coincideCoordenadaY = (fin.getY() == inicio.getY()-indiceY);
				}
				
				coincideCoordenadaX = (fin.getX() == inicio.getX()+indiceX);
			
			} else {
				if (deltaY > 0 ) {
					Posicion nuevaPosicion = new Posicion(inicio.getX()-indiceX,inicio.getY()+indiceY);
					this.agregarUnaPosicion(nuevaPosicion);
					coincideCoordenadaY = (fin.getY() == inicio.getY()+indiceY);
				} else {
					Posicion nuevaPosicion = new Posicion(inicio.getX()-indiceX,inicio.getY()-indiceY);
					this.agregarUnaPosicion(nuevaPosicion);
					coincideCoordenadaY = (fin.getY() == inicio.getY()-indiceY);
				}
			
				coincideCoordenadaX = (fin.getX() == inicio.getX()-indiceX);
			}
			indiceX+=Trayectoria.getPaso();
			indiceY+=Trayectoria.getPaso();		
		}
		
		//Guardo la ultima posicion agregada para luego completar el trayecto
		Posicion posicionAuxiliar = this.trayecto.getLast();
		if (coincideCoordenadaX && !coincideCoordenadaY) { agregarTramoVertical(posicionAuxiliar,fin);}
		if (coincideCoordenadaY && !coincideCoordenadaX) { agregarTramoHorizontal(posicionAuxiliar,fin);}

	}

	private static int getPaso() {
		// TODO Auto-generated method stub
		return PASO;
	}

	private void agregarTramoHorizontal(Posicion posicionAuxiliar, Posicion fin) {
		
		int indice = posicionAuxiliar.getX();
		
		while (indice != fin.getX()) {
			
			if (fin.getX() - posicionAuxiliar.getX() > 0) {
				Posicion nuevaPosicion = new Posicion (indice++,fin.getY());
				this.agregarUnaPosicion(nuevaPosicion);
			} else {
				Posicion nuevaPosicion = new Posicion (indice--,fin.getY());
				this.agregarUnaPosicion(nuevaPosicion);
			}
		}
		
		this.agregarUnaPosicion(fin);
		
	}

	private void agregarTramoVertical(Posicion posicionAuxiliar, Posicion fin) {
	
		int indice = posicionAuxiliar.getY();
		
		while (indice != fin.getY()) {
			
			if (fin.getY() - posicionAuxiliar.getY() > 0) {
				Posicion nuevaPosicion = new Posicion (fin.getX(),indice++);
				this.agregarUnaPosicion(nuevaPosicion);
			} else {
				Posicion nuevaPosicion = new Posicion (fin.getX(),indice--);
				this.agregarUnaPosicion(nuevaPosicion);
			}
		}
		
		this.agregarUnaPosicion(fin);
		
	}
	
	public boolean tienePosicion(Posicion unaPosicion) {
		
		boolean resultado = false;
		
		Iterator<Posicion> iterador = this.trayecto.iterator();
		
		while (iterador.hasNext()) {
			Posicion posicionAuxiliar = iterador.next();
			if (posicionAuxiliar.getX() == unaPosicion.getX()){
				if(posicionAuxiliar.getY() == unaPosicion.getY()){
					resultado = true;
				}
			}
		}
		
		return resultado;
	}
	
//	public LinkedList<Posicion> getTrayecto () {return this.trayecto;}
	
}
